package com.yunzai.login.controller;

import com.yunzai.generic.domain.JSONResult;
import com.yunzai.secure.domain.LoginUser;
import com.yunzai.secure.exception.ServiceException;
import com.yunzai.login.domain.Login;
import com.yunzai.login.service.ILoginService;
import com.yunzai.login.utils.CaptchaGenerator;
import com.yunzai.generic.service.IRedisService;
import com.yunzai.secure.util.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
public class LoginController {

    // 验证码字符集（排除易混淆字符）
    private static final String CHAR_SET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
    private static final int CODE_LENGTH = 4; // 验证码长度
    private static final String CODE_KEY_PREFIX = "yunzai_api_login_code:";

    private static final int RETRY_NUMBER= 5; // 验证码重试次数
    private static final String CODE_RETRY_NUMBER_KEY_PREFIX = "yunzai_api_login_code_retry_number:";

    private static final String USER_LOCK_KEY_PREFIX = "yunzai_api_login_user_lock:";

    @Autowired
    private IRedisService redisService;

    @Autowired
    private ILoginService loginService;

    @GetMapping("/code")
    public JSONResult code() {
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < CODE_LENGTH; i++) {
            int index = random.nextInt(CHAR_SET.length());
            code.append(CHAR_SET.charAt(index));
        }
        String uuid = UUID.randomUUID().toString().replace("-", "");
        String key = CODE_KEY_PREFIX + uuid;
        // 存储到Redis，设置过期时间（例如5分钟）
        redisService.setValue(key, code, 5, TimeUnit.MINUTES);
        // 将验证码转为Base64
        String base64Code = null;
        try {
            base64Code = CaptchaGenerator.getBase64(code.toString());
        } catch (IOException e) {
            throw new ServiceException("生成验证码失败", e);
        }
        JSONResult data = new JSONResult();
        data.put("code", base64Code);
        data.put("uuid", uuid);
        return JSONResult.success(data);
    }

    @PostMapping("/login")
    public JSONResult login(@RequestBody Login login) {
        verifyCode(login.getCode(), login.getUuid(),login.getUsername());
        LoginUser loginUser = new LoginUser();
        loginUser.setUsername(login.getUsername());
        loginUser.setPassword(login.getPassword());
        String token = loginService.login(loginUser);
        return JSONResult.success("登陆成功！",token);
    }

    private void verifyCode(String code, String uuid, String username) {
        String isLock = redisService.getValue(USER_LOCK_KEY_PREFIX + username);
        if ("true".equals(isLock)) {
            throw new ServiceException("验证码错误次数已达上限！请10分钟后重试！");
        }
        String key = CODE_KEY_PREFIX + uuid;
        String storedCode = redisService.getValue(key);
        Integer retryNumber = redisService.getValue(CODE_RETRY_NUMBER_KEY_PREFIX + username);
        if (storedCode == null) {
            throw new ServiceException("验证码已过期！");
        } else if (!storedCode.equalsIgnoreCase(code)) {
            if (retryNumber != null) {
                if (retryNumber >= RETRY_NUMBER) redisService.setValue(USER_LOCK_KEY_PREFIX + username, "true", 10, TimeUnit.MINUTES);
                redisService.setValue(CODE_RETRY_NUMBER_KEY_PREFIX + username, retryNumber + 1, 1, TimeUnit.MINUTES);
            } else {
                redisService.setValue(CODE_RETRY_NUMBER_KEY_PREFIX + username, 1, 1, TimeUnit.MINUTES);
            }
            redisService.deleteValue(key);
            throw new ServiceException("验证码错误!");
        }
        redisService.deleteValue(key);
    }

    @GetMapping("/getInfo")
    public JSONResult getUserInfo() {
        return JSONResult.success(SecurityUtil.getLoginUser());
    }

}
